﻿//-----------------------------------------------------------------------
// <copyright file="SQLiteConnection.SQLiteTransaction.cs" company="NextLine Software">
//     Copyright (c) NextLine Software. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace NextLine.Data.SQLite
{
    using System;
    using System.Data;
    using NextLine.Data.SQLite.Wrapper;

    public partial class SQLiteConnection
    {
        private class SQLiteTransaction : IDbTransaction
        {
            private readonly SQLiteConnection connection;
            private readonly IsolationLevel isolationLevel;
            private bool transactionOpen;

            public SQLiteTransaction(SQLiteConnection connection, IsolationLevel isolationLevel)
            {
                this.connection = connection;
                this.isolationLevel = isolationLevel;
                if (connection.connectionState != ConnectionState.Open)
                {
                    throw new InvalidOperationException("Transactions can only opened started on open connections.");
                }

                if (Sqlite3.sqlite3_exec(this.connection.databaseHandle, "BEGIN", 0, 0, 0) != Sqlite3.SQLITE_OK)
                {
                    string errorMessage = Sqlite3.sqlite3_errmsg(this.connection.databaseHandle);
                    throw new SQLiteException(errorMessage);
                }
                
                this.transactionOpen = true;
            }

            public IDbConnection Connection
            {
                get
                {
                    return this.connection;
                }
            }

            public IsolationLevel IsolationLevel
            {
                get
                {
                    return this.isolationLevel;
                }
            }

            public void Commit()
            {
                if (!this.transactionOpen)
                {
                    throw new InvalidOperationException("Cannot commit a transaction which is not open.");
                }

                if (Sqlite3.sqlite3_exec(this.connection.databaseHandle, "COMMIT", 0, 0, 0) != Sqlite3.SQLITE_OK)
                {
                    string errorMessage = Sqlite3.sqlite3_errmsg(this.connection.databaseHandle);
                    throw new SQLiteException(errorMessage);
                }

                this.transactionOpen = false;
            }

            public void Rollback()
            {
                try
                {
                    if (this.transactionOpen)
                    {
                        if (Sqlite3.sqlite3_exec(this.connection.databaseHandle, "ROLLBACK", 0, 0, 0) != Sqlite3.SQLITE_OK)
                        {
                            string errorMessage = Sqlite3.sqlite3_errmsg(this.connection.databaseHandle);
                            throw new SQLiteException(errorMessage);
                        }
                    }
                }
                finally
                {
                    this.transactionOpen = false;
                }
            }

            public void Dispose()
            {
                this.Rollback();
            }
        }
    }
}
